﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Linq;
using Hydra.Shell.QueryProviders;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Xml.Linq;
using System.ServiceModel.DomainServices.Client;
using HydraQueryProvider.QueryProviders;

namespace Hydra.Shell
{
    public class HydraQueryable<T> : ObservableCollection<T>, IQueryable<T>, IExpressionProcessorClient
    {
        private System.Linq.Expressions.Expression expression;
        private OnProcessExpressionHandler[] handlers; 
        public event OnProcessExpressionHandler OnProcessExpression;

        public HydraQueryable()
        {
            expression = System.Linq.Expressions.Expression.Constant(this);
        }
        
        public HydraQueryable(IEnumerable<T> collection, OnProcessExpressionHandler[] handlers) : base(collection)
        {
            expression = System.Linq.Expressions.Expression.Constant(this);
            this.handlers = handlers;
        }
        
        public HydraQueryable(IEnumerable<T> collection) : base(collection)
        {
            expression = System.Linq.Expressions.Expression.Constant(this);
        }
        
        public HydraQueryable(List<T> list) : base(list)
        {
            expression = System.Linq.Expressions.Expression.Constant(this);
        }

        public Type ElementType
        {
            get 
            { 
                return typeof(T);
            }
        }

        public System.Linq.Expressions.Expression Expression
        {
            get 
            {
                return expression;
            }
        }

        public IQueryProvider Provider
        {
            get 
            {
                var provider = new HydraQueryProvider<T>(this);

                provider.OnProcessExpression += (XElement element, string path, out object result) =>
                {
                    result = null;

                    if (OnProcessExpression != null)
                    {
                        OnProcessExpression(element, path, out result);
                    }

                    if (handlers != null)
                    {
                        foreach (var handler in handlers)
                        {
                            handler(element, path, out result);
                        }
                    }
                };

                return provider;
            }
        }

        public System.Collections.IEnumerator GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }
}
